/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package tools.ga;

import java.util.Arrays;
import java.util.Random;

/**
 *
 * @author asus
 */
public class Individual implements Cloneable, Comparable<Individual> {

    private SearchspaceAndProblem searchspaceAndProblem;
    private Boolean[] x;
    private float fitness = 0;
    Random random = new Random();

    /**
     * @return the fx
     */
    public float getFitness() {
        return fitness == 0 ? searchspaceAndProblem.evaluate(this) : fitness;
    }

    /**
     * @param fx the fx to set
     */
    public void setFitness(float fx) {
        this.fitness = fx;
    }

    /**
     * @return the x
     */
    public Boolean[] getX() {
        if (x.length == 0) {
            x = new Boolean[this.searchspaceAndProblem.questionList.size()];
            for (int i = 0; i < x.length; i++) {
                x[i] = random.nextBoolean();
            }
        }
        return x;
    }

    /**
     * @param x the x to set
     */
    public void setX(Boolean[] x) {
        this.x = x;
    }

    /**
     * @return the searchspaceAndProblem
     */
    public SearchspaceAndProblem getSearchspaceAndProblem() {
        return searchspaceAndProblem;
    }

    /**
     * @param searchspaceAndProblem the searchspaceAndProblem to set
     */
    public void setSearchspaceAndProblem(SearchspaceAndProblem searchspaceAndProblem) {
        this.searchspaceAndProblem = searchspaceAndProblem;
    }

    public void mutate(int muatateNum) throws CloneNotSupportedException {
        for (int i = 0; i < muatateNum; i++) {
            int r = random.nextInt(this.x.length);
            this.x[r] = !this.x[r];
        }
    }

    public Individual[] crossover(Individual anotherIndividual) throws CloneNotSupportedException {
        Individual[] result = {this.clone(), anotherIndividual.clone()};
        int rand = random.nextInt(this.x.length);
        Boolean[] a = Arrays.copyOfRange(result[0].getX(), 0, rand - 1);
        Boolean[] a1 = Arrays.copyOf(result[0].getX(), rand);
        Boolean[] b = Arrays.copyOfRange(result[1].getX(), 0, rand - 1);
        Boolean[] b1 = Arrays.copyOf(result[1].getX(), rand);

        System.arraycopy(a, 0, result[0].getX(), 0, a.length);
        System.arraycopy(b1, 0, result[0].getX(), a.length, b1.length);
        System.arraycopy(b, 0, result[1].getX(), 0, b.length);
        System.arraycopy(a1, 0, result[1].getX(), b.length, a1.length);
        return result;
    }

    /**
     *
     * @return @throws java.lang.CloneNotSupportedException
     */
    @Override
    public Individual clone() throws CloneNotSupportedException {
        return (Individual) super.clone();
    }

    @Override
    public int compareTo(Individual t) {
        int result;
        if (this.getFitness() == t.getFitness()) {
            result = 0;
        } else if (this.getFitness() > t.getFitness()) {
            result = 1;
        } else {
            result = -1;
        }
        return result;
    }
}
